package EventManager;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;

public class EventManager
{
	private static EventManager ref;
	private LinkedList<EventType> m_activeEvents;
	private LinkedList<EventType> m_eventQue;
	private LinkedList<Listener> m_listenerList;
	private long m_startTime;

	private EventManager()
	{
		m_listenerList = new LinkedList<Listener>();
		m_eventQue = new LinkedList<EventType>();
		m_activeEvents = new LinkedList<EventType>();
		m_startTime = System.currentTimeMillis();
	}
	public static EventManager getInstance()
	{
		if (ref == null)
			// it's ok, we can call this constructor
			ref = new EventManager();
		return ref;
	}
	// Check for duplicates before adding the listener
	boolean addListener(Listener listener)
	{
		if (!searchListenerList(listener))
		{
			m_listenerList.addFirst(listener);
			return true;
		}
		return false;
	}
	/**
	 * Deletes listener from the ListenerList
	 */
	boolean deleteListener(Listener listener)
	{
		if (m_listenerList.contains(listener))
		{
			m_listenerList.remove(listener);
			return true;
		}
		return false;
	}
	// always returns true.... maybe add an exception here some where
	// adds an event to the m_eventQue
	boolean queueEvent(EventType event)
	{
		if (m_eventQue.size() == 0)
		{
			m_eventQue.addLast(event);
			return true;
		} else if (event.getName().equals(m_eventQue.getLast().getName()))
		{
			m_eventQue.removeLast();
			m_eventQue.addLast(event);
			return true;
		} else
		{
			m_eventQue.addLast(event);
			return true;
		}
	}
	boolean queueEvent(String eventName)
	{
		// Create the event to add based on the passed in char
		EventType event = new EventType(eventName);
		if (m_eventQue.size() == 0)
		{
			m_eventQue.addLast(event);
			return true;
		}
		if (eventName.equals(m_eventQue.getLast().getName()))
		{
			m_eventQue.removeLast();
			m_eventQue.addLast(event);
		} else
		{
			m_eventQue.addLast(event);
			return true;
		}
		return false;
	}
	void deleteEvent(EventType event)
	{
		m_eventQue.remove(event);
	}
	boolean deleteEvent(String eventName)
	{
		// deletes every event with this name
		// TODO warning may be implemented incorrectly because it is expecting
		// to only delete one event, while this deletes all with the same name
		for (EventType e : m_eventQue)
		{
			if (e.getName().equals(eventName))
			{
				m_eventQue.remove(e);
				return true;
			}
		}
		return false;
	}
	// not implemented
	void triggerEvent(EventType event)
	{
	}
	// not implemented
	void triggerEvent(String[] eventName)
	{
	}
	// search for duplicate listener
	boolean searchListenerList(Listener listener)
	{
		return m_listenerList.contains(listener);
	}
	void processEvents()
	{
		System.out.format("size = %d", m_eventQue.size());
		// Only run for 5ms, getting called every gameloop
		long endTime = getTickCount() + 5;
		// Push all of EventQueue to ActiveQueue
		// Iterate through ActiveQueue until finished or endTime reached
		while (m_eventQue.size() > 0)
		{
			m_activeEvents.addLast(m_eventQue.getLast());
			m_eventQue.removeLast();
		}
		Iterator<Listener> it = m_listenerList.iterator();
		while ((m_activeEvents.size() > 0) && (it.hasNext()))
		{
			// TODO warning it handles differently in java, it may skip first
			// element
			Listener temp = it.next();
			if (getTickCount() > endTime)
			{
				return;
			} else if (temp.HandleEvent(m_activeEvents.getLast()))
			{
				m_activeEvents.removeLast();
			}
		}
	}
	private long getTickCount()
	{
		return System.currentTimeMillis() - m_startTime;
	}
}